#include "SysCtrl.h"

#include <strings.h>    //bzero
#include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <linux/input.h>



typedef struct 
{
    int x;
    int y;
}POINT;


void HMI_CtrlTestLoop()
{
    int fd = open("/dev/input/event0",O_RDONLY);
    if(fd<0)
    {
        printf("open /dev/input/event0 error retunn\n");
        return ;
    }

    struct input_event touchBuf;
    char xyFlag = 0;


    while(1)
    {
        bzero(&touchBuf,sizeof(touchBuf));
        ssize_t n = read(fd, &touchBuf, sizeof(touchBuf));
        if (n < 0)
        {
            perror("read error");
            break;
        }

        if(touchBuf.type == EV_ABS)
        {
            if((touchBuf.code == ABS_X) && (xyFlag == 0))
            {
                printf("(%d,",touchBuf.value);
                xyFlag = 1;
            }
            else if((touchBuf.code == ABS_Y) && (xyFlag ==1))
            {
                printf("%d)\n",touchBuf.value);
                xyFlag = 0;
            }
        }
    }
    
    close(fd);
}

void HMI_CtrlTest()
{
    int fd = open("/dev/input/event0",O_RDONLY);
    if(fd<0)
    {
        printf("open /dev/input/event0 error retunn\n");
        return ;
    }

    struct input_event touchBuf;
    char xyFlag = 0;

    // record the first and last point
    POINT pointFirst = {-1, -1};
    bool bFinishFirstPoint = false;
    POINT pointLast = {-1, -1};

    while(1)
    {
        bzero(&touchBuf,sizeof(touchBuf));
        ssize_t n = read(fd, &touchBuf, sizeof(touchBuf));
        if (n < 0)
        {
            perror("read error");
            break;
        }

        if(touchBuf.type == EV_ABS)
        {
            if((touchBuf.code == ABS_X) && (xyFlag == 0))
            {
                printf("(%d,",touchBuf.value);
                xyFlag = 1;
                if (!bFinishFirstPoint)
                {
                    pointFirst.x = touchBuf.value;
                }
                else
                {
                    pointLast.x = touchBuf.value;
                }
                
            }
            else if((touchBuf.code == ABS_Y) && (xyFlag ==1))
            {
                printf("%d)\n",touchBuf.value);
                xyFlag = 0;
                if (!bFinishFirstPoint)
                {
                    pointFirst.y = touchBuf.value;
                }
                else
                {
                    pointLast.y = touchBuf.value;
                }
            }

            if (!bFinishFirstPoint && pointFirst.x != -1 && pointFirst.y != -1)
            {
                printf("pointFirst.x = %d, pointFirst.y = %d\n",pointFirst.x,pointFirst.y);
                bFinishFirstPoint = true;
            }
        }

        if (touchBuf.type == EV_KEY)
        {
            if (touchBuf.code == BTN_TOUCH)
            {
                if (touchBuf.value == 0)
                    break;
            }
        }
    }


    printf("first point (x, y) = (%d, %d) \n", pointFirst.x, pointFirst.y);
    printf("last  point (x, y) = (%d, %d) \n", pointLast.x, pointLast.y);
    int deltaX = pointLast.x - pointFirst.x;
    int deltaY = pointLast.y - pointFirst.y;
    printf("delta point (x, y) = (%d, %d) \n", deltaX, deltaY);

    if (deltaX < 0)
    {
        printf("slide to the left\n");
    }
    else if (deltaX > 0)
    {
        printf("slide to the right\n");
   
    }
    else
    {
        printf("not slide\n");
    }
    

    close(fd);
    
}


#include <stdlib.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <string.h>

int LCD_CtrlTest()
{
    int fdLCD = open("/dev/fb0",O_RDWR);
    if(fdLCD == -1)
    {
        perror("打开LCD失败");    
        return -1;
    }

    /*
        void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset);
        功能：将一个文件或者其它对象映射进内存。
        参数：
            addr    : 映射到调用进程地址空间的起始地址，通常都是用NULL，让系统自动选定地址
            length  : 映射到调用进程地址空间的字节数
            prot    : 期望的内存保护标志，不能与文件的打开模式冲突。
                        PROT_READ 页内容可以被读取
                        PROT_WRITE 页可以被写入
            flags   : 指定映射对象的类型，映射选项和映射页是否可以共享。
                        MAP_SHARED 与其它所有映射这个对象的进程共享映射空间。对共享内容的修改与其它进程同步。
            fd      : 有效的文件描述词。如果MAP_ANONYMOUS被设定，为了兼容问题，其值应为-1
            offset  : 被映射对象内容的起点。 0代表完全重合

        返回值：
            成功执行时，mmap()返回被映射区的指针，失败时，mmap()返回MAP_FAILED[其值为(void *)-1]
    */
    int32_t *p = (int32_t *)mmap(NULL, 800*480*4, PROT_READ | PROT_WRITE, MAP_SHARED, fdLCD, 0);

    // 3, 准备好红绿蓝三种颜色的数据
    int32_t blue = 0x000000FF;
    int32_t green= 0x0000FF00;
    int32_t red  = 0x00FF0000;

    //定义一个数组，来方便切换颜色
    int32_t colors[] = {blue, green, red};
    int sizeOfColors = sizeof(colors)/sizeof(colors[0]);

    // 4, 铺满整个映射内存
    int k = 0;
    while(1)
    {
        for(int j=0; j<480; j++)//j是行数
        {
            for(int i=0; i<800; i++)//i是列数
            {
                //每次移动4个字节(1个int32)，到下一个像素点，到了行末，再加会自动跳到下一行
                memcpy(p+i+800*j, &colors[k % sizeOfColors], 4);
            }
        }

        // 切换颜色
        k++;
        sleep(1);
    }

    // 5, 释放资源
    munmap(p, 800*480*4);
    close(fdLCD);

    return 0;
}

int LCD_ShowColorsInRow()
{
    int fdLCD = open("/dev/fb0",O_RDWR);
    if(fdLCD == -1)
    {
        perror("打开LCD失败");    
        return -1;
    }

    int32_t *p = (int32_t *)mmap(NULL, 800*480*4, PROT_READ | PROT_WRITE, MAP_SHARED, fdLCD, 0);


    // 颜色
    int32_t blue = 0x000000FF;
    int32_t green= 0x0000FF00;
    int32_t red  = 0x00FF0000;
    int32_t orange = 0x00FFA500;
    int32_t yellow = 0x00FFFF00;
    int32_t pink = 0x00FFC0CB;
    int32_t cyan = 0x0000FFFF;  //青色
    int32_t purple = 0x00800080;


    //定义一个数组，来方便切换颜色
    int32_t colors[] = {blue, green, red, orange, yellow, pink, cyan, purple};
    int sizeOfColors = sizeof(colors)/sizeof(colors[0]);


    int k = 0;
    int rowScale = 480 / sizeOfColors;
    while(1)
    {
        for(int j=0; j<480; j++)
        {
            
            if ( (j % rowScale == 0) && j!=0)
            {
                k = (k + 1) % sizeOfColors;
            }

            for(int i=0; i<800; i++)
            {
                //每次移动4个字节(1个int32)，到下一个像素点，到了行末，再加会自动跳到下一行
                memcpy(p+i+800*j, &colors[k], 4);
            }
        }

        sleep(1);
    }

    // 5, 释放资源
    munmap(p, 800*480*4);
    close(fdLCD);

}

int LCD_ShowColorsInColumn()
{
    int fdLCD = open("/dev/fb0",O_RDWR);
    if(fdLCD == -1)
    {
        perror("打开LCD失败");    
        return -1;
    }

    int32_t *p = (int32_t *)mmap(NULL, 800*480*4, PROT_READ | PROT_WRITE, MAP_SHARED, fdLCD, 0);


    // 颜色
    int32_t blue = 0x000000FF;
    int32_t green= 0x0000FF00;
    int32_t red  = 0x00FF0000;
    int32_t orange = 0x00FFA500;
    int32_t yellow = 0x00FFFF00;
    int32_t pink = 0x00FFC0CB;
    int32_t cyan = 0x0000FFFF;  //青色
    int32_t purple = 0x00800080;


    //定义一个数组，来方便切换颜色
    int32_t colors[] = {blue, green, red, yellow, orange, pink, purple, cyan};
    int sizeOfColors = sizeof(colors)/sizeof(colors[0]);


    unsigned int kOffset = 0;
    int scale = 800 / sizeOfColors;
    while(1)
    {
        for(int j=0; j<480; j++)
        {
            for(int i=0; i<800; i++)
            {
                // 两种方向的效果
                int colorIndex = (i / scale + sizeOfColors - kOffset) % sizeOfColors;
                // int colorIndex = (i / scale + kOffset) % sizeOfColors;
                
                //每次移动4个字节(1个int32)，到下一个像素点，到了行末，再加会自动跳到下一行
                memcpy(p+i+800*j, &colors[colorIndex], 4);
            }
        }

        if (kOffset == sizeOfColors - 1)
        {
            kOffset = 0;
        }
        else
        {
            kOffset++;
        }
        sleep(1);
    }
    
    // 5, 释放资源
    munmap(p, 800*480*4);
    close(fdLCD);

}


int LCD_ShowColorsInBlock()
{
    printf("LCD_ShowColorsInBlock ------------- \n");
    int fdLCD = open("/dev/fb0",O_RDWR);
    if(fdLCD == -1)
    {
        perror("打开LCD失败");    
        return -1;
    }

    int32_t *p = (int32_t *)mmap(NULL, 800*480*4, PROT_READ | PROT_WRITE, MAP_SHARED, fdLCD, 0);


    // 颜色
    int32_t blue = 0x000000FF;
    int32_t green= 0x0000FF00;
    int32_t red  = 0x00FF0000;
    int32_t orange = 0x00FFA500;
    int32_t yellow = 0x00FFFF00;
    int32_t pink = 0x00FFC0CB;
    int32_t cyan = 0x0000FFFF;  //青色
    int32_t purple = 0x00800080;


    //定义一个数组，来方便切换颜色
    int32_t colors[] = {blue, green, red, yellow, orange, pink, purple, cyan};
    int sizeOfColors = sizeof(colors)/sizeof(colors[0]);

    unsigned int kOffset = 0;

    while(1)
    {
        for(int j=0; j<480; j++)
        {
            for(int i=0; i<800; i++)
            {
                // 两种方向的效果
                // int colorIndex = (ReturnBlockIndex(i, j, sizeOfColors) + kOffset) % sizeOfColors;
                int colorIndex = (ReturnBlockIndex(i, j, sizeOfColors) + sizeOfColors - kOffset) % sizeOfColors;

                //每次移动4个字节(1个int32)，到下一个像素点，到了行末，再加会自动跳到下一行
                memcpy(p+i+800*j, &colors[colorIndex], 4);
            }
        }

        if (kOffset == sizeOfColors - 1)
        {
            kOffset = 0;
        }
        else
        {
            kOffset++;
        }
        sleep(1);
    }

    // 5, 释放资源
    munmap(p, 800*480*4);
    close(fdLCD);
}

int ReturnBlockIndex(int pointX, int pointY, int blockSize)
{
    // printf("ReturnBlockIndex ----blockSize = %d--------- \n", blockSize);
    if (blockSize <= 0)
    {
        return -1;
    }
    else if (1 == blockSize)    // 0 or 1
    {
        return 0;
    }

    int xEachBlock = 800 / (blockSize / 2);
    int yEachBlock = 480 / 2;

    int xIndex = pointX / xEachBlock;
    int yIndex = pointY / yEachBlock;
    // printf("Position = (%d, %d), Index = (%d, %d) Indexvalue = %d\n", pointX, pointY, xIndex, yIndex, xIndex + yIndex * (blockSize / 2));

    return xIndex + yIndex * (blockSize / 2);

}



// 【6】驱动 --- 【7】字符设备驱动 --- 应用程序和驱动程序的区别
#define ON  0
#define OFF 1

#define  Beep_RD 	3
int FlipBeepStatus()
{
    while(1)
    {
        CtrlBeepStatus(true);
        GetBeepStatus();
        sleep(1);
        CtrlBeepStatus(false);
        GetBeepStatus();
        sleep(5);
    }
}

int CtrlBeepStatus(bool bSetOn)
{
    // 打开蜂鸣器
	int fd = open("/dev/beep", O_RDWR);
	int rt=0;
	if(fd == -1)
	{
		perror("open:");
		return -1;
	}

	if (bSetOn)
	{
        printf("CtrlBeepStatus: bSetOn = %d , turn on\n", bSetOn);
		ioctl(fd, ON, 1);
	}
	else
	{
        printf("CtrlBeepStatus: bSetOn = %d , turn off\n", bSetOn);
		ioctl(fd, OFF, 1);
	}

    close(fd);

    return 0;
}

int GetBeepStatus()
{
    // 打开蜂鸣器
	int fd = open("/dev/beep", O_RDWR);
	int rt=0;
	if(fd == -1)
	{
		perror("open:");
		return -1;
	}

    int state = ioctl(fd, Beep_RD, 1);
    printf("statue = %d\n--------------------\n",state);	//state：1

    close(fd);

    return state;
}